/*
 * Copyright 2013 Robert Peszek.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package fpig.concepts


/**
 * This class 'describes' Applicative Functor.  To be Applicative the 'thing' needs to be Functor first - this class extends {@code FunctorDescription}.
 * Monads logically imply Applicative (using conversion defined by {@link MonadAsApplicative}). 
 * To be a true Applicative, functor type mapping must obey applicative laws (see wiki page for more info).
 * <p>
 * Generics are used for informational purposes only and this info is lost in pure and bind methods.
 * <p>
 * Applicative is a powerful functional polymorphism.  Fpiglet includes a library of functions which work
 * on any Applicative {@link fpig.applicative.functions.BaseA}.  
 * Applicative also yields a coding style where operations on several functors are 'applied' to the functor values almost as if they
 * were regular objects.
 * <pre>
 * ApplicativeDescription a = FunListZipApplicative.instance
 * BaseA af = BaseA.getInstance(a)
 * def data1 = f ([10, 1, 2])
 * def data2 = f ([1,2,3,4])
 * def res = a.zipWith(PLUS, data1, data2)
 * assert [11, 3, 5] == funlistOut << res	
 * </pre>
 *
 * If you are comparing this to haskell {@code ap} is equivalent to {@code <*>} except for not being infix.
 * 
 * @see fpig.applicative.functions.BaseA
 * @see FunctorDescription
 * @see MonadDescription
 * @see MonadAsApplicative
 * @see <a href="http://code.google.com/p/fpiglet/wiki/ApplicativePolymorphism">http://code.google.com/p/fpiglet/wiki/ApplicativePolymorphism</a>
 * @author robert peszek
 *
 * @param <A> - type from
 * @param <F> - type to (Applicative Functor Type) 
 */
abstract class ApplicativeDescription<A,F> extends FunctorDescription<A,F> {
   
      
 /**
  * Returns pure closure which places element in applicative context.
  * <p> 
  * Logical signature
  * <pre>
  *    a -> f a //where f is applicative functor
  * </pre>
  * or to use generic info:
  * <pre>
  *  pure::  A -> F
  * </pre>
  */
   abstract Closure getPure()
   
   
 /**
  * Returns Applicative transformation.
  * <p>
  * Applicative transformation maps applicative functions to functions working on applicatives.
  * For example if applicative is {@link fpig.lists.structures.FunList} defined with zip applicative logic, ap allows to 
  * take a list of operations such as PLUS or TIMES and apply them to lists of elements. 
  * <p>
  * Logical signature.
  * <pre>
  *    ap :: f (a -> b) -> f a -> f b
  * </pre>
  *    
  * or to use generic info:
  * <pre>
  *    ap :: (A -> F) -> F -> F
  * </pre>
  * @see <a href="http://code.google.com/p/fpiglet/wiki/ApplicativePolymorphism">http://code.google.com/p/fpiglet/wiki/ApplicativePolymorphism</a>
  */
   abstract Closure getAp()
}

